﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using UnityEngine;

public class VIPMoudbusUtil {

    /// <summary>
    /// 字符串转换为Hex字符串
    /// </summary>
    /// <param name="str">字符串</param>
    /// <param name="encode">编码类型</param>
    /// <returns></returns>
    public static string StringToHexString(string str, Encoding encode)
    {
        var b = encode.GetBytes(str); //按照指定编码将string编程字节数组
        return b.Aggregate(string.Empty, (current, t) => current + "%" + Convert.ToString(t, 16));
    }

    /// <summary>
    /// Hex字符串转换为字符串
    /// </summary>
    /// <param name="hexStr">Hex字符串</param>
    /// <param name="encode">编码类型</param>
    /// <returns></returns>
    public static string HexStringToString(string hexStr, Encoding encode)
    {
        //以%分割字符串，并去掉空字符
        var chars = hexStr.Split(new[] { '%' }, StringSplitOptions.RemoveEmptyEntries);
        var b = new byte[chars.Length];
        //逐个字符变为16进制字节数据
        for (var i = 0; i < chars.Length; i++) b[i] = Convert.ToByte(chars[i], 16);

        //按照指定编码将字节数组变为字符串
        return encode.GetString(b);
    }

    /// <summary>
    /// Hex字符串转16进制字节数组
    /// </summary>
    /// <param name="hexStr">Hex字符串</param>
    /// <returns></returns>
    public static byte[] HexStringToHexBytes(string hexStr)
    {
        hexStr = hexStr.Replace(" ", "");
        if (hexStr.Length % 2 != 0)
            hexStr += " ";
        var returnBytes = new byte[hexStr.Length / 2];
        for (var i = 0; i < returnBytes.Length; i++)
            returnBytes[i] = Convert.ToByte(hexStr.Substring(i * 2, 2), 16);
        return returnBytes;
    }

    /// <summary>
    /// 字节数组转16进制字符串
    /// </summary>
    /// <param name="bytes">bytes</param>
    /// <returns></returns>
    public static string BytesToHexString(byte[] bytes)
    {
        const string returnStr = "";
        return bytes == null ? returnStr : bytes.Aggregate(returnStr, (current, t) => current + t.ToString("X2"));
    }

    /// <summary>
    /// 将byte[]转换成int
    /// </summary>
    /// <param name="bytes">需要转换成整数的byte数组</param>
    public static int BytesToInt(byte[] bytes)
    {
        //如果传入的字节数组长度小于4,则返回0
        if (bytes.Length < 4) return 0;
        //定义要返回的整数
        var num = 0;
        //如果传入的字节数组长度大于4,需要进行处理
        if (bytes.Length < 4) return num;
        //创建一个临时缓冲区
        var tempBuffer = new byte[4];
        //将传入的字节数组的前4个字节复制到临时缓冲区
        Buffer.BlockCopy(bytes, 0, tempBuffer, 0, 4);
        //将临时缓冲区的值转换成整数，并赋给num
        num = BitConverter.ToInt32(tempBuffer, 0);
        //返回整数
        return num;
    }

    /// <summary>
    /// bytes字节数组转换为float类型
    /// </summary>
    /// <param name="bytes">byte字节数组</param>
    /// <returns></returns>
    public static float BytesToFloat(byte[] bytes)
    {
        var data = BytesToHexString(bytes);
        var num = uint.Parse(data, NumberStyles.AllowHexSpecifier);
        var floatValues = BitConverter.GetBytes(num);
        return BitConverter.ToSingle(floatValues, 0);
    }

    /// <summary>
    /// bytes数据转换为long类型
    /// </summary>
    /// <param name="bytes">byte数据</param>
    /// <returns></returns>
    public static long BytesToLong(byte[] bytes)
    {
        var data = BytesToHexString(bytes);
        var num = ulong.Parse(data, NumberStyles.AllowHexSpecifier);
        return (long)num;
    }

    /// <summary>
    /// CRC16校验
    /// </summary>
    /// <param name="bytes"></param>
    /// <returns></returns>
    public static byte[] CRC16(byte[] bytes)
    {
        //设置所有为1
        ushort crc = 0xFFFF;
        var len = bytes.Length;
        if (len <= 0)
        {
            crc = 0;
        }
        else
        {
            len--;
            uint ix;
            for (ix = 0; ix <= len; ix++)
            {
                crc = (ushort)(crc ^ bytes[ix]);
                uint iy;
                for (iy = 0; iy <= 7; iy++)
                    if ((crc & 1) != 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);
                    else
                        crc = (ushort)(crc >> 1); //
            }
        }
        var buf1 = (byte)((crc & 0xff00) >> 8); //高位置
        var buf2 = (byte)(crc & 0x00ff); //低位置
        crc = (ushort)(buf1 << 8);
        crc += buf2;
        var strA = crc.ToString("x4");
        var result = HexStringToHexBytes(strA);
        var b = new byte[2];
        b[0] = result[1];
        b[1] = result[0];
        return b;
    }

    //-----------------------------------------------------------------------------------------------------

    /// <summary>
    /// 16进制字符串转byte[] 48 65 6C 6C 6F 20 57 6F 72 6C 64 21
    /// </summary>
    /// <param name="hexValues"></param>
    /// <returns></returns>
    public static byte[] HexStringToByteArray(string hexValues)
    {
        string[] hexValuesSplit = hexValues.Split(' ');
        byte[] val = new byte[hexValuesSplit.Length];
        int i = 0;
        foreach (string hex in hexValuesSplit)
        {
            int value = HexStringToInt(hex);
            val[i] = (byte)value;
            i++;
        }
        return val;
    }

    /// <summary>
    /// 2位16进制转int
    /// </summary>
    /// <param name="hex"></param>
    /// <returns></returns>
    public static int HexStringToInt(string hex)
    {
        int num1 = 0;
        int num2 = 0;
        char[] nums = hex.ToCharArray();
        if (hex.Length == 2)
        {
            for (int i = 0; i < nums.Length; i++)
            {
                string strNum = nums[i].ToString().ToUpper();
                switch (strNum)
                {
                    case "A":
                        strNum = "10";
                        break;
                    case "B":
                        strNum = "11";
                        break;
                    case "C":
                        strNum = "12";
                        break;
                    case "D":
                        strNum = "13";
                        break;
                    case "E":
                        strNum = "14";
                        break;
                    case "F":
                        strNum = "15";
                        break;
                    default:
                        break;
                }
                if (i == 0)
                {
                    num1 = int.Parse(strNum) * 16;
                }
                if (i == 1)
                {
                    num2 = int.Parse(strNum);
                }
            }
        }
        return num1 + num2;
    }

}
